package com.ruoyi.auth.utils.token;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class TokenUtils {

    // 从配置文件中读取JWT的密钥，用于签名和验证Token
    @Value("${jwt.secret}")
    private String secret;

    // 从配置文件中读取JWT的过期时间，单位为毫秒
    @Value("${jwt.expiration}")
    private long expiration;

    /**
     * 根据给定的主题（例如用户ID、手机号等）生成一个JWT Token
     *
     * @param subject 要包含在Token中的主题信息，如手机号
     * @return 生成的JWT Token字符串
     */
    public String generateToken(String subject) {
        // 创建一个存储Token中自定义声明（Claims）的Map
        Map<String, Object> claims = new HashMap<>();
        // 将主题信息放入Claims中
        claims.put("sub", subject);

        Date now = new Date();
        Date expirationDate = new Date(now.getTime() + expiration);

        return Jwts.builder()
                // 设置Token中的Claims
               .setClaims(claims)
                // 设置Token的签发时间
               .setIssuedAt(now)
                // 设置Token的过期时间
               .setExpiration(expirationDate)
                // 使用指定的签名算法和密钥对Token进行签名
               .signWith(SignatureAlgorithm.HS256, secret)
                // 生成紧凑的Token字符串
               .compact();
    }

    /**
     * 解析给定的JWT Token并返回其中的Claims信息
     * 如果解析失败（例如Token无效、签名错误等），则返回null
     *
     * @param token 要解析的JWT Token字符串
     * @return 解析后的Claims对象，如果解析失败则为null
     */
    public Claims parseToken(String token) {
        try {
            return Jwts.parser()
                    // 设置用于验证Token签名的密钥
                   .setSigningKey(secret)
                    // 解析Token并获取Claims
                   .parseClaimsJwt(token)
                   .getBody();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 验证给定的JWT Token是否有效
     * 主要检查Token是否过期以及签名是否正确
     *
     * @param token 要验证的JWT Token字符串
     * @return 如果Token有效则返回true，否则返回false
     */
    public boolean validateToken(String token) {
        Claims claims = parseToken(token);
        if (claims == null) {
            return false;
        }
        // 检查Token是否过期
        return!claims.getExpiration().before(new Date());
    }
}
